package com.lc.activiti.process.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lc.activiti.process.dao.TaskGoingFlowDao;
import com.lc.activiti.process.entity.TaskGoingFlow;
import com.lc.activiti.process.service.TaskGoingFlowService;
import org.activiti.bpmn.model.*;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.task.Task;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;



import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * 流程任务线路记录(TaskGoingFlow)表服务实现类
 *
 * @author 骆超
 * @since 2021-06-16 16:51:54
 */
@Service("taskGoingFlowService")
public class TaskGoingFlowServiceImpl extends ServiceImpl<TaskGoingFlowDao, TaskGoingFlow> implements TaskGoingFlowService {

    @Resource
    private RepositoryService repositoryService;
    @Resource
    private HistoryService historyService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveGoingFlow(Task task,String type) {
        //获取流程模型
        BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
        //找出所有已进行的节点
        List<HistoricActivityInstance> activityInstances =
                historyService.createHistoricActivityInstanceQuery()
                        .processInstanceId(task.getProcessInstanceId())
                        .orderByHistoricActivityInstanceStartTime()
                        .desc().list();
        switch (type){
            case "start":
                List<SequenceFlow> flowList = new ArrayList<>();
                activityInstances.forEach(v-> {
                    //遍历找出节点
                    FlowElement flowElement = bpmnModel.getMainProcess()
                            .getFlowElement(v.getActivityId(), true);
                    //获取节点的进线集合
                    flowList.addAll(this.collectSeqFlows(flowElement));
                });
                //初始化一个路线集合
                List<TaskGoingFlow> goingFlows = new ArrayList<>();
                //将进线集合遍历，实例化为路线实例，塞入路线集合中
                flowList.stream().distinct().forEach(f->{
                    goingFlows.add(new TaskGoingFlow().setProcessInstanceId(task.getProcessInstanceId()).setGoingFlow(f.getId()).setSourceRef(f.getSourceRef()).setTargetRef(f.getTargetRef()));
                });
                //批量保存路线
                saveBatch(goingFlows);
                break;
            case "audit":
            default:
                //初始化一个路线集合
                TaskGoingFlow taskGoingFlow = new TaskGoingFlow().setProcessInstanceId(task.getProcessInstanceId());
                //因为按照时间倒序排列，所以倒数第二个，应该是路线的出点
                FlowElement source = bpmnModel.getMainProcess()
                        .getFlowElement(activityInstances.get(1).getActivityId(), true);
                //路线的结点
                FlowElement target = bpmnModel.getMainProcess()
                        .getFlowElement(activityInstances.get(0).getActivityId(), true);
                //获取结点中的进线集合
                List<SequenceFlow> incomingFlows = this.collectSeqFlows(target);
                //如果是分支的话，审批时与用户任务节点同时进行，分支进线未保存，所以也需要保存分支进线
                if (source instanceof ExclusiveGateway){
                    List<SequenceFlow> gateWayFlows = this.collectSeqFlows(source);
                    baseMapper.insert(new TaskGoingFlow()
                            .setProcessInstanceId(task.getProcessInstanceId())
                            .setGoingFlow(gateWayFlows.get(0).getId())
                            .setSourceRef(gateWayFlows.get(0).getSourceRef())
                            .setTargetRef(gateWayFlows.get(0).getTargetRef())
                    );
                }
                taskGoingFlow.setTargetRef(target.getId());
                taskGoingFlow.setSourceRef(source.getId());
                //根据出点和结点，找到所走路线，将该id放入路线中关联
                incomingFlows.stream().filter(i->i.getSourceRef().equals(taskGoingFlow.getSourceRef())&&i.getTargetRef().equals(taskGoingFlow.getTargetRef())).findFirst().ifPresent(m->taskGoingFlow.setGoingFlow(m.getId()));
                //保存路线
                taskGoingFlow.insert();
                break;
        }
    }

    /**
     * 获取进线
     * @author 骆超
     * @date 2021/6/22
     * @param flowElement 任务节点
     * @return java.util.List<org.activiti.bpmn.model.SequenceFlow>
     */
    List<SequenceFlow>  collectSeqFlows(FlowElement flowElement){
        List<SequenceFlow> flowList = new ArrayList<>();
        if (flowElement instanceof UserTask){
            UserTask userTask = (UserTask) flowElement;
            flowList.addAll(userTask.getIncomingFlows());
        }else if (flowElement instanceof StartEvent){
            StartEvent startEvent = (StartEvent) flowElement;
            flowList.addAll(startEvent.getIncomingFlows());
        }else if (flowElement instanceof ExclusiveGateway){
            ExclusiveGateway gateway = (ExclusiveGateway) flowElement;
            flowList.addAll(gateway.getIncomingFlows());
        }else if (flowElement instanceof EndEvent){
            EndEvent endEvent = (EndEvent) flowElement;
            flowList.addAll(endEvent.getIncomingFlows());
        }
        return flowList;
    }
}
